package com.ly.blog_common.excel;

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.formula.functions.T;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * excel核心处理点
 *
 * @author ly
 * create at 2021/8/30 - 10:27
 **/
public class ExcelCore {

    /**
     * 导出excel核心方法
     * @param title 标题
     * @param className 实体类名
     * @param list 数据实体
     * @param excelExportType 导出类名格式
     * @return excel对象
     * @throws Exception 异常
     */
    public HSSFWorkbook exportExcel(String title,Class className,List<T> list,ExcelExportType excelExportType) throws Exception {

        // 获取属性
        Field[] fields = className.getDeclaredFields();
        List<Field> fieldList = new ArrayList<>();

        getExcelColumnName(fields,fieldList);

        int columnsize = fieldList.size(), rowindex = 0;
        // 创建一个HSSFWorbook对象（excel的文档对象）
        HSSFWorkbook hWorkbook = new HSSFWorkbook();
        // 创建一个HSSFSheet对象（excll的表单）
        HSSFSheet hSheet = hWorkbook.createSheet();
        // 创建行（excel的行）
        HSSFRow hRow = hSheet.createRow(rowindex++);
        // 设置行高度
        hRow.setHeight((short) 380);
        // 创建单元格（从0开始）
        HSSFCell hCell = hRow.createCell((short) 0);
        // 样式对象
        HSSFCellStyle cellStyle = getCellStyle(hWorkbook, (short) 300, (short) 500);
        // 将上面获得的样式对象给对应单元格
        hCell.setCellStyle(cellStyle);
        // 设置标题行
        hCell.setCellValue(title);

        if (fieldList.isEmpty() || list == null || list.isEmpty()) {
            return hWorkbook;
        }

        // 创建第二行，代表列名
        hRow = hSheet.createRow(rowindex++);
        cellStyle = getCellStyle(hWorkbook, (short) 270, (short) 500);
        generateTitle(excelExportType, fieldList, columnsize, hSheet, hRow, cellStyle);

        // 组装excel的数据
        cellStyle = getCellStyle(hWorkbook, (short) 220, (short) 500);// 设置单元格格式
        generateData(list, fieldList, columnsize, rowindex, hSheet, cellStyle);

        /**
         * 第1个参数：从哪一行开始 第2个参数：到哪一行结束 第3个参数：从哪一列开始 第4个参数：到哪一列结束
         */
        hSheet.addMergedRegion(new CellRangeAddress(0, 0, 0, columnsize - 1));

        // 固定表头（前一个参数代表列，后一个参数单表行）
        hSheet.createFreezePane(0, 2);
        return hWorkbook;
    }

    private int generateData(List<T> list,
                              List<Field> fieldList,
                              int columnsize,
                              int rowindex,
                              HSSFSheet hSheet,
                              HSSFCellStyle cellStyle) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        HSSFRow hRow;
        HSSFCell hCell;
        for (Object model : list) {
            hRow = hSheet.createRow(rowindex++);
            // 获取该类
            Class clazz = model.getClass();
            for (int i = 0; i < columnsize; i++) {
                Field field = fieldList.get(i);
                try {
                    // 获取该字段的注解对象
                    // 获取方法名
                    String methodName;
                    Method method;
                    Object result;
                    if(model instanceof Map) {
                        methodName = "get";
                        method = Map.class.getMethod(methodName, Object.class);
                        result = method.invoke(model, field.getName());
                    }else{
                        // 获取方法名
                        methodName = "get" + field.getName().substring(0, 1).toUpperCase()
                                + field.getName().substring(1);
                        method = clazz.getMethod(methodName);
                        // 获取该字段的注解对象
                        result = method.invoke(model);
                    }

                    hCell = hRow.createCell((short) i);
                    if (result != null) {
                        if (result.getClass().isAssignableFrom(Date.class)) {
                            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ");
                            result = format.format(result);
                        }
                        hCell.setCellValue(new HSSFRichTextString(result.toString()));
                    } else {
                        hCell.setCellValue(new HSSFRichTextString("-"));
                    }
                    hCell.setCellStyle(cellStyle);
                } catch (IllegalArgumentException e) {
                    System.out.println(e.getMessage());
                }
            }
        }
        return rowindex;

    }

    protected void generateTitle(ExcelExportType excelExportType,
                                 List<Field> fieldList,
                                 int columnsize,
                                 HSSFSheet hSheet,
                                 HSSFRow hRow,
                                 HSSFCellStyle cellStyle) {
        HSSFCell hCell;
        for (int i = 0; i < columnsize; i++) {
            Field field = fieldList.get(i);
            if (field.isAnnotationPresent(ExcelAnnotation.class)) {
                // 获取该字段的注解对象
                ExcelAnnotation anno = field.getAnnotation(ExcelAnnotation.class);
                hCell = hRow.createCell((short) i);
                String colName = field.getAnnotation(ExcelAnnotation.class).name().length > excelExportType.getExportType()
                        ? field.getAnnotation(ExcelAnnotation.class).name()[excelExportType.getExportType()]
                        : field.getAnnotation(ExcelAnnotation.class).name()[0];
                hCell.setCellValue(colName);
                hCell.setCellStyle(cellStyle);
                hSheet.setColumnWidth((short) i, (short) anno.width());
            }
        }
    }


    /**
     * 获取展示的列名 - 通过对象类判定，而非实际对象
     * @param fields 对象字段集合
     * @param fieldList 返回的字段集合
     */
    protected void getExcelColumnName(Field[] fields, List<Field> fieldList) {
        for (Field fie : fields) {
            if (fie.isAnnotationPresent(ExcelAnnotation.class)) {
                fieldList.add(fie);
            }
        }
        // 按照 order 进行排序
        Collections.sort(fieldList, (f1, f2)->
                f1.getAnnotation(ExcelAnnotation.class).order()
                        - f2.getAnnotation(ExcelAnnotation.class).order()
        );
    }


    /**
     * 功能 :设置excel表格默认样式
     *
     * @param hWorkbook
     *            需导出Excel数据
     * @param fontHeight
     *            字体粗度
     * @param boldWeight
     *            表格线的粗度
     * @return
     */
    protected HSSFCellStyle getCellStyle(HSSFWorkbook hWorkbook, short fontHeight, short boldWeight) {
        HSSFCellStyle cellStyle;
        HSSFFont font;
        cellStyle = hWorkbook.createCellStyle();
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setTopBorderColor(IndexedColors.BLACK.index);
        cellStyle.setLeftBorderColor(IndexedColors.BLACK.index);
        cellStyle.setRightBorderColor(IndexedColors.BLACK.index);
        cellStyle.setBottomBorderColor(IndexedColors.BLACK.index);
        font = hWorkbook.createFont();
        font.setFontHeight(fontHeight);
        font.setBold(true);
        font.setFontName("宋体");
        cellStyle.setFont(font);
        cellStyle.setWrapText(true);
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        return cellStyle;
    }

}
